package com.hsy.swu.home.course

import android.content.Context
import android.os.Bundle
import android.util.Base64
import android.view.Gravity
import android.view.View.OnClickListener
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.forEachIndexed
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.room.Room
import com.hsy.swu.MyConfig
import com.hsy.swu.R
import com.hsy.swu.clouddb.MyUser
import com.hsy.swu.databinding.FragmentCourseBinding
import com.hsy.swu.home.HomeFragmentViewModel
import com.hsy.swu.hsyutils.HsyFragment
import com.hsy.swu.hsyutils.MActivityUtil
import com.hsy.swu.hsyutils.MLog
import com.hsy.swu.hsyutils.setFont
import com.hsy.swu.hsyutils.spRead
import com.hsy.swu.hsyutils.spWrite
import com.hsy.swu.roomdb.AppDatabase
import com.hsy.swu.roomdb.CourseDao
import com.hsy.swu.widget.updateSimpleCourseModelFile
import com.kongzue.dialogx.customwheelpicker.CustomWheelPickerDialog
import com.kongzue.dialogx.customwheelpicker.interfaces.OnCustomWheelPickerSelected
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.time.LocalDate

class CourseFragment : HsyFragment<FragmentCourseBinding, HomeFragmentViewModel>() {
    companion object {
        private const val CUSTOM_BG = "customBg"
        private var bgByteArray = byteArrayOf() // 就这一个要持久化的数据，干脆不用 viewModel，直接用伴生类

        fun readCustomBg(context: Context) {
            val customBgStr = context.spRead(CUSTOM_BG)
            bgByteArray = Base64.decode(customBgStr, Base64.DEFAULT)
        }

        fun clearCustomBg(context: Context) {
            bgByteArray = byteArrayOf()
            context.spWrite("", CUSTOM_BG)
        }
    }

    private lateinit var courseDao: CourseDao
    private var crtUser: MyUser = MyUser.currentUser // 当前正在看的课表的 user
    private var currentCourse: CourseModel? = null // 当前正在上的课
    private var maskView: TextView? = null

    override fun createViewModel(): HomeFragmentViewModel {
        return ViewModelProvider(requireActivity())[HomeFragmentViewModel::class.java]
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        refreshWhenWeekChangedObserver()

        setClick()

        courseDao = Room.databaseBuilder(
            requireContext(),
            AppDatabase::class.java,
            "swu"
        ).build().courseDao()
    }

    override fun onResume() {
        super.onResume()
        mBinding.root.post {
            getCourseFromRoomDBAndRefreshUI()
        }
        mViewModel.mBinder?.getService()?.setGetCourseListener { courseList ->
            MLog.attention("got course -> ${courseList.size}")
            if (courseList.isEmpty()) return@setGetCourseListener
            val account = courseList[0].account

            if (account == MyUser.currentUser.account) {
                lifecycleScope.launch {
                    withContext(Dispatchers.IO) {
                        // 如果是当前用户，则更新 courseWidget读取的文件
                        requireContext().updateSimpleCourseModelFile(courseList)
                    }
                }
            }

            if (account == crtUser.account && isResumed) {
                getCourseFromRoomDBAndRefreshUI()
            }
        }
    }

    override fun onPause() {
        super.onPause()
        mBinding.constraintLayout.removeView(maskView)
    }

    private fun markCurrentTime() {
        mBinding.constraintLayout.removeView(maskView)
        // 星期数 linearLayout
        val currentDayOfWeekValue = LocalDate.now().dayOfWeek.value
        mBinding.linearDayOfWeek.getChildAt(currentDayOfWeekValue).apply {
            setBackgroundResource(R.drawable.bg_course_mark)
            (this as AppCompatTextView).setTextColor(resources.getColor(R.color.blue))
        }
        mBinding.linearDayValue.getChildAt(currentDayOfWeekValue).apply {
            setBackgroundResource(R.drawable.bg_course_mark)
            (this as AppCompatTextView).setTextColor(resources.getColor(R.color.blue))
        }

        // 上课时间 linearLayout
        val currentSection = CourseModel.getCurrentSection() ?: return

        // 课表 constraintLayout
        lifecycleScope.launch {
            if (mBinding.courseTableViewGroup.currentWeek.value != MyConfig.currentWeek) {
                return@launch
            }
            val width = mBinding.linearDayOfWeek.measuredWidth / 8
            val height = mBinding.linearCourseTime.measuredHeight / 14
            maskView = TextView(requireContext()).apply {
                setBackgroundResource(R.drawable.bg_course_mark)
                elevation = 50f
                setTextColor(resources.getColor(R.color.blue))
                text = "当前课时"
                if (currentCourse == null) {
                    if (CourseModel.nowTimeIsInSection()) {
                        textSize = 14f
                        gravity = Gravity.CENTER
                        layoutParams = ConstraintLayout.LayoutParams(width, height).apply {
                            leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID
                            topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                            setMargins(
                                (currentDayOfWeekValue - 1) * width,
                                (currentSection - 1) * height,
                                0, 0
                            )
                        }
                    } else {
                        return@launch
                    }
                } else {
                    textSize = 8f
                    gravity = Gravity.BOTTOM or Gravity.CENTER
                    layoutParams = ConstraintLayout.LayoutParams(
                        width,
                        currentCourse!!.totalSection * height
                    ).apply {
                        leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID
                        topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                        setMargins(
                            (currentDayOfWeekValue - 1) * width,
                            (currentCourse!!.startSection - 1) * height,
                            0, 0
                        )
                    }
                }
                setFont()
            }
            mBinding.constraintLayout.addView(maskView)
            maskView!!.animate().scaleX(0f).scaleY(0f).setDuration(0L).start() // 先缩到最小
            MActivityUtil.scaleAnimOnShow(maskView!!)
        }
    }

    private fun setClick() {
        val onWeekPickerClickListener = OnClickListener {
            val startWeek = mBinding.courseTableViewGroup.currentWeek.value ?: 1
            CustomWheelPickerDialog.build()
                .setTitle("请选择周数")
                .addWheel((1..20).map { "第 $it 周" }.toTypedArray())
                .setDefaultSelect(0, startWeek - 1)
                .setOnWheelChangeListener { _, _, _, index, _ ->
                    mBinding.courseTableViewGroup.currentWeek.postValue(index + 1)
                }
                .show(object : OnCustomWheelPickerSelected() {
                    override fun onSelected(
                        p0: CustomWheelPickerDialog?,
                        p1: String?,
                        p2: Array<out String>?,
                        p3: IntArray?
                    ) {
                    }
                })
        }
        mBinding.week.setOnClickListener(onWeekPickerClickListener)
        mBinding.btnExpand.setOnClickListener(onWeekPickerClickListener)
    }

    private fun refreshWhenWeekChangedObserver() {
        mBinding.courseTableViewGroup.let { viewGroup ->
            viewGroup.currentWeek.observe(this) {
                viewGroup.checkCourseIsInWeek(it)
                mBinding.apply {
                    week.text = "第 $it 周"
                    month.text = "${viewGroup.dateList[it * 7 - 1].second}" // 获取当前看的这周的周日的月份
                    linearDayValue.forEachIndexed { index, tv ->
                        // 第一个 TextView不是显示日期的，所以跳过
                        if (index != 0)
                            (tv as TextView).text =
                                "${viewGroup.dateList[(it - 1) * 7 + index - 1].third}"
                    }
                }

                markCurrentTime()
            }
        }
    }

    private fun getCourseFromRoomDBAndRefreshUI() {
        lifecycleScope.launch {
            mBinding.name.text = crtUser.nickName
            val courseDBList: List<CourseModel>
            val customCourseList: List<CourseModel>
            withContext(Dispatchers.IO) {
                courseDBList = courseDao.getAllByAccount(crtUser.account)
                customCourseList = if (crtUser.account == MyUser.currentUser.account) {
                    courseDao.getAllCustomCourse()
                } else {
                    emptyList()
                }
            }
            mBinding.courseTableViewGroup.apply {
                courseList = courseDBList.toMutableList().apply {
                    addAll(customCourseList)
                }
                removeAllViews()
            }

            if (courseDBList.isNotEmpty()) {
                currentCourse = CourseModel.getCurrentCourse(courseDBList)
            }

            markCurrentTime()
        }
    }
}